package com.weifly.weistock.module.stockbill.parse;


import com.weifly.weistock.core.common.StockException;
import com.weifly.weistock.core.constant.StockBillColumnTypeEnum;
import com.weifly.weistock.module.stockbill.StockBillParseService;
import com.weifly.weistock.module.stockbill.bo.BillHeadColumn;
import com.weifly.weistock.module.stockbill.bo.BillParseContext;
import com.weifly.weistock.module.stockbill.bo.StockRecordBO;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 自动判断的对账单解析服务
 *
 * @author weifly
 * @since 2021/05/14
 */
public class AutoJudgeBillParseService implements StockBillParseService {

    private List<AbstractBillAnalyzer> analyzerList;

    public List<AbstractBillAnalyzer> getAnalyzerList() {
        return analyzerList;
    }

    public void setAnalyzerList(List<AbstractBillAnalyzer> analyzerList) {
        this.analyzerList = analyzerList;
    }

    @Override
    public List<StockRecordBO> parseRecord(File recordFile) throws IOException {
        try (FileInputStream fileInput = new FileInputStream(recordFile)) {
            return this.parseRecord(fileInput);
        }
    }

    @Override
    public List<StockRecordBO> parseRecord(InputStream input) throws IOException {
        BillParseContext context = new BillParseContext();
        List<String> lineList = this.readLines(input);
        // 解析head
        this.parseHeadInfo(context, lineList);
        // 验证head
        this.checkHeadInfo(context.getHeadColumnList());
        // 解析line
        return this.parseLines(context, lineList);
    }

    private List<String> readLines(InputStream input) throws IOException {
        List<String> lineList = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(input, "GBK"));
        String line;
        while ((line = reader.readLine()) != null) {
            lineList.add(line);
        }
        return lineList;
    }

    private void parseHeadInfo(BillParseContext context, List<String> lineList) {
        for (AbstractBillAnalyzer analyzer : this.analyzerList) {
            List<BillHeadColumn> headColumnList = analyzer.analyzeHead(lineList);
            if (headColumnList != null && headColumnList.size() > 0) {
                context.setBillAnalyzer(analyzer);
                context.setHeadColumnList(headColumnList);
                return;
            }
        }
        throw new StockException("无法解析headLine");
    }

    private void checkHeadInfo(List<BillHeadColumn> columnList) {
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.DATE) == null) {
            throw new StockException("缺少列：发生日期");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.TIME) == null) {
            throw new StockException("缺少列：成交时间");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.BUSINESS_NAME) == null) {
            throw new StockException("缺少列：业务名称");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.STOCK_CODE) == null) {
            throw new StockException("缺少列：证券代码");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.STOCK_NAME) == null) {
            throw new StockException("缺少列：证券名称");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.TRADE_PRICE) == null) {
            throw new StockException("缺少列：成交价格");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.TRADE_NUMBER) == null) {
            throw new StockException("缺少列：成交数量");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.FEE_SERVICE) == null) {
            throw new StockException("缺少列：手续费");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.FEE_STAMP) == null) {
            throw new StockException("缺少列：印花税");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.FEE_TRANSFER) == null) {
            throw new StockException("缺少列：过户费");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.FEE_CLEAR) == null) {
            throw new StockException("缺少列：交易所清算费");
        }
        // 华宝证券没有此列
//        if (findHeadColumn(columnList, BillColumnTypeEnum.CLEAR_AMOUNT) == null) {
//            throw new StockException("缺少列：发生金额");
//        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.AFTER_AMOUNT) == null) {
            throw new StockException("缺少列：资金本次余额");
        }
        if (findHeadColumn(columnList, StockBillColumnTypeEnum.ENTRUST_CODE) == null) {
            throw new StockException("缺少列：委托编号");
        }
    }

    private BillHeadColumn findHeadColumn(List<BillHeadColumn> columnList, StockBillColumnTypeEnum columnType) {
        for (BillHeadColumn column : columnList) {
            if (column.getColumnType() == columnType) {
                return column;
            }
        }
        return null;
    }

    private List<StockRecordBO> parseLines(BillParseContext context, List<String> lineList) {
        List<StockRecordBO> recordList = new ArrayList<>();
        for (String line : lineList) {
            if (StringUtils.isBlank(line) || line.startsWith("----") || line.startsWith(context.getHeadColumnList().get(0).getColumnName())) {
                continue;
            }
            StockRecordBO recordBO = context.getBillAnalyzer().analyzeOneRecord(context, line);
            if (recordBO != null) {
                this.checkStockRecord(recordBO, line);
                recordList.add(recordBO);
            }
        }
        return recordList;
    }

    private void checkStockRecord(StockRecordBO recordBO, String line) {
        if (StringUtils.isBlank(recordBO.getDate())) {
            throw new StockException("缺少值：发生日期, line=" + line);
        }
        if (StringUtils.isBlank(recordBO.getTime())) {
            throw new StockException("缺少值：成交时间, line=" + line);
        }
        if (recordBO.getBusinessName() == null) {
            throw new StockException("缺少值：业务名称, line=" + line);
        }
        if (StringUtils.isBlank(recordBO.getStockCode())) {
            throw new StockException("缺少值：证券代码, line=" + line);
        }
        if (StringUtils.isBlank(recordBO.getStockName())) {
            throw new StockException("缺少值：证券名称, line=" + line);
        }
        if (recordBO.getTradePrice() == null || recordBO.getTradePrice() <= 0) {
            throw new StockException("成交价格为空或小于等于0, line=" + line);
        }
        if (recordBO.getTradeNumber() == null || recordBO.getTradeNumber() <= 0) {
            throw new StockException("成交数量为空或小于等于0, line=" + line);
        }
        if (recordBO.getFeeService() == null) {
            throw new StockException("手续费为空, line=" + line);
        }
        if (recordBO.getFeeStamp() == null) {
            throw new StockException("印花税为空, line=" + line);
        }
        if (recordBO.getFeeTransfer() == null) {
            throw new StockException("过户费为空, line=" + line);
        }
        if (recordBO.getFeeClear() == null) {
            throw new StockException("交易所清算费为空, line=" + line);
        }
        if (recordBO.getClearAmount() == null) {
            throw new StockException("发生金额为空, line=" + line);
        }
        if (recordBO.getAfterAmount() == null) {
            throw new StockException("资金本次余额为空, line=" + line);
        }
        if (StringUtils.isBlank(recordBO.getEntrustCode())) {
            throw new StockException("委托编号为空, line=" + line);
        }
    }
}
